package com.syh.jn.scm.service.impl.supplier.stock;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.operation.entity.supplier.OperaSupplier;
import com.syh.jn.scm.domain.operation.event.supplier.OperaSupplierEvent;
import com.syh.jn.scm.domain.supplier.entity.stock.StockSpill;
import com.syh.jn.scm.domain.supplier.entity.stock.StockSpillItem;
import com.syh.jn.scm.domain.supplier.event.StockSpillEvent;
import com.syh.jn.scm.domain.supplier.repository.stock.StockSpillRepository;
import com.syh.jn.scm.dto.supplier.stock.StockSpillItemVo;
import com.syh.jn.scm.dto.supplier.stock.StockSpillMto;
import com.syh.jn.scm.dto.supplier.stock.StockSpillSto;
import com.syh.jn.scm.dto.supplier.stock.StockSpillVo;
import com.syh.jn.scm.service.api.supplier.stock.StockSpillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 报溢单管理
 */
@Service
@Transactional
public class StockSpillServiceImpl extends AbstractServiceImpl<StockSpillSto, StockSpillMto, StockSpillVo, StockSpill, Long> implements StockSpillService {
  @Autowired
  private StockSpillRepository stockSpillRepository;

  @Override
  protected AggregateRepository<StockSpill, Long> getAggregateRepository() {
    return stockSpillRepository;
  }

  /**
   * 保存报溢单和报溢单项
   *
   * @param sto
   * @return
   */
  @Override
  public Long save(StockSpillSto sto) {
    StockSpill stockSpill = new StockSpill(sto);
    return stockSpillRepository.add(stockSpill);
  }

  /**
   * 修改报溢单和报溢单项
   *
   * @param mto
   */
  @Override
  public void update(StockSpillMto mto) {
    StockSpill stockSpill = this.getStockSpillById(mto.getId());
    stockSpill.modify(mto);
    stockSpillRepository.update(stockSpill);
  }

  /**
   * 删除报溢单和报溢单项
   *
   * @param id
   */
  @Override
  public void delete(Long id) {
    StockSpill stockSpill = this.getStockSpillById(id);
    stockSpill.destroy();
    stockSpillRepository.remove(stockSpill);
  }

  @Override
  public StockSpillVo getById(Long id) {
    StockSpillVo stockSpillVo = stockSpillRepository.getKeyView(id);
    stockSpillVo.setItems(stockSpillRepository.getItemVosById(id));
    return stockSpillVo;
  }

  /**
   * 根据id获取报溢聚合体
   *
   * @param id
   * @return
   */
  @Override
  public StockSpillVo getVo(Long id) {
    //获取报损项聚合体
    StockSpill stockSpill = stockSpillRepository.getById(id);
    ExtAssert.notNull(stockSpill, "对象为空");

    //业务模型转Vo
    StockSpillVo vo = new StockSpillVo();
    List<StockSpillItemVo> itemVoList = new ArrayList<>();
    ExtBeanUtils.copyProperties(stockSpill, vo);
    stockSpill.getSpillItems().stream().forEach(item -> {
      StockSpillItemVo stockOverflowItemVo = new StockSpillItemVo();
      ExtBeanUtils.copyProperties(item, stockOverflowItemVo);

      itemVoList.add(stockOverflowItemVo);
    });

    vo.setItems(itemVoList);
    return vo;
  }

  /**
   * 获取明细对象
   *
   * @param id      明细id
   * @param goodsId 明细中商品id
   * @return
   */
  @Override
  public StockSpillItemVo getItemByIdAndGoodsId(Long id, Long goodsId) {
    return this.entityTransVo(stockSpillRepository.getItemByIdAndGoodsId(id,goodsId));
  }

  /**
   * 取消订单
   *
   * @param id 自增id
   */
  @Override
  public void cancel(Long id) {
    StockSpill stockSpill = this.getStockSpillById(id);
    stockSpill.cancel();
    stockSpillRepository.updateStatus(stockSpill);
  }

  /**
   * 解锁
   *
   * @param id 自增id
   */
  @Override
  public void unLock(Long id) {
    StockSpill stockSpill = this.getStockSpillById(id);
    stockSpill.unLock();
    stockSpillRepository.updateStatus(stockSpill);
  }

  /**
   * 确认报溢单
   *
   * @param id
   */
  @Override
  public void enabled(Long id) {
    StockSpill stockSpill = this.getStockSpillById(id);
    stockSpill.enabled();
    stockSpillRepository.updateStatus(stockSpill);

    //发送事件
    Object[] obj = new Object[]{stockSpill};
    this.publicEvent(StockSpillEvent.buildStockSpillConfirmStatus(obj));
  }

  /**
   * 未确认报溢单
   *
   * @param id
   */
  @Override
  public void disabled(Long id) {
    StockSpill stockSpill = this.getStockSpillById(id);
    stockSpill.disabled();
    stockSpillRepository.updateStatus(stockSpill);

    //发送事件
    Object[] obj = new Object[]{stockSpill};
    this.publicEvent(StockSpillEvent.buildStockSpillUnConfirmStatus(obj));
  }

  /**
   * 消费者：监听服务商反开账（删除所有该服务商的报溢单）
   */
  @DomainEventHandle(OperaSupplierEvent.SUPPLIER_REVERSAL_ACCOUNT)
  protected void handleSupplierReversalAccount(OperaSupplier supplier) {
    this.stockSpillRepository.deleteByBusinessEntityId(supplier.getId());
  }

  /**
   * 根据id获取报溢单并且判空
   *
   * @param id
   * @return
   */
  private StockSpill getStockSpillById(Long id) {
    ExtAssert.notNull(id, "id为空");

    StockSpill stockSpill = stockSpillRepository.getById(id);
    ExtAssert.notNull(stockSpill, "对象为空");

    return stockSpill;
  }

  /**
   * 领域对象转vo
   *
   * @param entity
   * @return
   */
  private StockSpillItemVo entityTransVo(StockSpillItem entity) {
    StockSpillItemVo vo = new StockSpillItemVo();
    ExtBeanUtils.copyProperties(entity, vo);
    return vo;
  }
}
